//
//  NvPlayer.m
//  NvPlayer
//
//  Created by bmd on 2017/3/29.
//  Copyright © 2016年 bmd. All rights reserved.
//
#define WeakSealf(weakself) __weak typeof(self) weakself = self;
#import "NvPlayer.h"
#import "Utils.h"

@interface NvPlayer()
{
    BOOL isIntoBackground;
    AVPlayerItem *_playerItem;
    AVPlayerLayer *_playerLayer;
    id _playTimeObserver; // 播放进度观察者
    CGFloat windowLevel;
    NSTimer *timer;
}
@property (weak, nonatomic) IBOutlet UIView *playerView;
@property(nonatomic,assign)CGRect oldFrame;
@property (nonatomic, assign) NSTimeInterval lastTime;

@property (nonatomic, strong) UIView *bottomView;
@property (nonatomic, strong) UIButton *playButton;
//@property (nonatomic, strong) UIButton *fullButton;
@property (nonatomic, strong) UILabel *currentTime;
@property (nonatomic, strong) UILabel *totalTime;
@property (nonatomic, strong) UISlider *playSliderProgress;
@property (nonatomic, strong) UIButton *player_Pause;

@end
@implementation NvPlayer

+(instancetype)palyer {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"NvSellerResource" ofType:@"bundle"];
    NSBundle *myBundle = [NSBundle bundleWithPath:path];
    return [[myBundle loadNibNamed:@"NvPlayer" owner:self options:nil] firstObject];
}

-(void)awakeFromNib
{
    [super awakeFromNib];
    
    [self setUp];

}

- (void)setOldFrame:(CGRect)rect {
    _oldFrame = rect;
}

-(instancetype)initWithFrame:(CGRect)frame
{
    self=[super initWithFrame:frame];
    if (self) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"NvSellerResource" ofType:@"bundle"];
        NSBundle *myBundle = [NSBundle bundleWithPath:path];
        self=[[myBundle loadNibNamed:@"NvPlayer" owner:self options:nil] firstObject];
        self.frame=frame;
        _oldFrame=frame;
        [self setUp];
    }
     return self;
}

- (void)setUp {
    self.player = [[AVPlayer alloc] init];
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    [self.playerView.layer addSublayer:_playerLayer];
    
    self.bottomView = [[UIView alloc] initWithFrame:CGRectZero];
    self.bottomView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
    [self addSubview:self.bottomView];
    
    self.playButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.playButton.frame = CGRectZero;
    [self.playButton setImage:[self imageWithName:@"player_stop"] forState:UIControlStateNormal];
    [self.playButton setImage:[self imageWithName:@"player_play"] forState:UIControlStateSelected];
    [self.playButton addTarget:self action:@selector(playOrPause) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:self.playButton];
    
    self.currentTime = [[UILabel alloc] initWithFrame:CGRectZero];
    self.currentTime.textAlignment = NSTextAlignmentCenter;
    self.currentTime.textColor = [UIColor whiteColor];
    self.currentTime.text = @"00:00";
    self.currentTime.font = [UIFont systemFontOfSize:12.0f];
    [self addSubview:self.currentTime];
    
    self.totalTime = [[UILabel alloc] initWithFrame:CGRectZero];
    self.totalTime.textAlignment = NSTextAlignmentCenter;
    self.totalTime.textColor = [UIColor whiteColor];
    self.totalTime.text = @"00:00";
    self.totalTime.font = [UIFont systemFontOfSize:12.0f];
    [self addSubview:self.totalTime];
    
    self.playSliderProgress = [[UISlider alloc] initWithFrame:CGRectZero];
    [self.playSliderProgress setThumbImage:[self imageWithName:@"player_slide"] forState:UIControlStateNormal];
    [self.playSliderProgress addTarget:self action:@selector(sliderChange) forControlEvents:UIControlEventValueChanged];
    [self addSubview:self.playSliderProgress];
    
    self.player_Pause = [UIButton buttonWithType:UIButtonTypeCustom];
    self.player_Pause.frame = CGRectZero;
    [self.player_Pause setImage:[self imageWithName:@"player_preview"] forState:UIControlStateNormal];
    [self.player_Pause setImage:[self imageWithName:@"player_preview"] forState:UIControlStateHighlighted];
    [self.player_Pause addTarget:self action:@selector(play) forControlEvents:UIControlEventTouchUpInside];
    self.player_Pause.hidden = YES;
    [self addSubview:self.player_Pause];
    
    [self setClipsToBounds:YES];
    [self startTimer];
    
    [self setPortraitLayout];
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    windowLevel = window.windowLevel;
}

- (void)startTimer {
    timer = [NSTimer scheduledTimerWithTimeInterval:4 target:self selector:@selector(hidenBottom) userInfo:nil repeats:NO];
}

- (void)sliderChange {
    [self pause];
    //转换成CMTime才能给player来控制播放进度
    CMTime dragedCMTime = CMTimeMake(self.playSliderProgress.value, 1);
    [_playerItem seekToTime:dragedCMTime];
}

- (void)playOrPause {
    if (_isPlaying) {
        [self pause];
    }else{
        [self play];
    }
}

- (void)fullScreen {
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    if (_isFull) {
        window.windowLevel = windowLevel;
        //创建一个CGAffineTransform  transform对象
        CGAffineTransform  transform;
        //设置旋转度数
        transform = CGAffineTransformRotate(self.transform,-M_PI/2.0);
        //动画开始
        [UIView beginAnimations:@"rotate" context:nil];
        //动画时常
        [UIView setAnimationDuration:0.5];
        //获取transform的值
        [self setTransform:transform];
        //关闭动画
        [UIView commitAnimations];
        [self setPortraitLayout];
        _isFull=NO;
        
    }else{
        window.windowLevel = UIWindowLevelStatusBar + 1;
        
        //创建一个CGAffineTransform  transform对象
        CGAffineTransform  transform;
        //设置旋转度数
        transform = CGAffineTransformRotate(self.transform,M_PI/2.0);
        //动画开始
        [UIView beginAnimations:@"rotate" context:nil];
        //动画时常
        [UIView setAnimationDuration:0.5];
        //获取transform的值
        [self setTransform:transform];
        //关闭动画
        [UIView commitAnimations];
        [self setlandscapeLayout];
        _isFull=YES;
    }
}

// 后台
- (void)resignActiveNotification{
    NSLog(@"进入后台");
    isIntoBackground = YES;
    [self pause];
}

- (void)layoutSubviews{
    [super layoutSubviews];
    self.playerView.frame = self.bounds;
    _playerLayer.frame = self.bounds;
    
    self.player_Pause.frame = CGRectMake((self.playerView.width_LL-52)/2, (self.playerView.height_LL-52)/2, 52, 52);
    
    self.bottomView.frame = CGRectMake(0, self.playerView.height_LL-44, self.playerView.width_LL, 44);
    
    self.playButton.frame = CGRectMake(0, self.playerView.height_LL-44, 44, 44);
    self.currentTime.frame = CGRectMake(self.playButton.right_LL, self.playerView.height_LL-44, 44, 44);
    self.totalTime.frame = CGRectMake(self.playerView.width_LL-44, self.playerView.height_LL-44, 44, 44);
    
    self.playSliderProgress.frame = CGRectMake(self.currentTime.right_LL, self.currentTime.centerY_LL-15, self.playerView.width_LL-142, 30);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    if (self.playButton.bottom_LL<=self.playerView.bottom_LL) {
        [self hidenBottom];
    } else if (self.playButton.bottom_LL>self.playerView.bottom_LL) {
        [self showBottom];
    }
}

- (void)hidenBottom {
    [UIView animateWithDuration:0.3 animations:^{
        self.playButton.top_LL += 44;
        self.currentTime.top_LL += 44;
        self.totalTime.top_LL += 44;
        self.playSliderProgress.top_LL += 44;
        self.bottomView.top_LL += 44;
    } completion:^(BOOL finished) {
        [timer invalidate];
    }];
}

- (void)showBottom {
    [UIView animateWithDuration:0.3 animations:^{
        self.playButton.top_LL -= 44;
        self.currentTime.top_LL -= 44;
        self.totalTime.top_LL -= 44;
        self.playSliderProgress.top_LL -= 44;
        self.bottomView.top_LL -= 44;
    } completion:^(BOOL finished) {
        [self startTimer];
    }];
}

- (void)updatePlayerWith:(NSURL *)url{
    if (_playerItem) {
        [self removeObserverAndNotification];
    }
    _playerItem = [AVPlayerItem playerItemWithURL:url];
    _playerItem.seekingWaitsForVideoCompositionRendering = YES;
    [_player replaceCurrentItemWithPlayerItem:_playerItem];
    [self addObserverAndNotification];
}

- (void)updatePlayerWithAsset:(AVAsset *)asset {
    if (_playerItem) {
        [self removeObserverAndNotification];
    }
    _playerItem = [AVPlayerItem playerItemWithAsset:asset];
    _playerItem.seekingWaitsForVideoCompositionRendering = YES;
    [_player replaceCurrentItemWithPlayerItem:_playerItem];
    [self addObserverAndNotification];
}

- (void)addObserverAndNotification{
    [_playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];// 监听status属性
    [_playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听缓冲进度
    [self monitoringPlayback:_playerItem];// 监听播放状态
    [self addNotification];
}

-(void)addNotification{
    //给AVPlayerItem添加播放完成通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    // 后台
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resignActiveNotification) name:UIApplicationDidEnterBackgroundNotification object:nil];
}

-(void)playbackFinished:(NSNotification *)notification{
    NSLog(@"视频播放完成.");
    _playerItem = [notification object];
    [_playerItem seekToTime:kCMTimeZero];
    [self pause];
}

#pragma mark - KVO - status
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    AVPlayerItem *item = (AVPlayerItem *)object;
    if ([keyPath isEqualToString:@"status"]) {
        if (isIntoBackground) {
            return;
        }else{
            if ([item status] == AVPlayerStatusReadyToPlay) {
                NSLog(@"AVPlayerStatusReadyToPlay");
                CMTime duration = item.duration;// 获取视频总长度
                NSLog(@"%f", CMTimeGetSeconds(duration));
                [self setMaxDuratuin:CMTimeGetSeconds(duration)];
                [self play];
            }else if([item status] == AVPlayerStatusFailed) {
                NSLog(@"AVPlayerStatusFailed");
            }else{
                NSLog(@"AVPlayerStatusUnknown");
            }
        }
    }else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        CMTime duration = _playerItem.duration;
        CGFloat totalDuration = CMTimeGetSeconds(duration);
        self.lastTime = totalDuration;
    }else if (object == _playerItem && [keyPath isEqualToString:@"playbackBufferEmpty"])
    {
        if (_playerItem.playbackBufferEmpty) {
            //Your code here
            NSLog(@"bufer Empty---");
        }
    }
    
    else if (object == _playerItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"])
    {
        if (_playerItem.playbackLikelyToKeepUp)
        {
            //Your code here
            NSLog(@"keep up");

        }
    }

}

- (NSTimeInterval)availableDurationRanges {
    NSArray *loadedTimeRanges = [_playerItem loadedTimeRanges];
    CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
    float startSeconds = CMTimeGetSeconds(timeRange.start);
    float durationSeconds = CMTimeGetSeconds(timeRange.duration);
    NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度
    return result;
}
#pragma mark - 移除通知&KVO
- (void)removeObserverAndNotification{
    NSLog(@"开始清除KVO和通知");

    [_player replaceCurrentItemWithPlayerItem:nil];
    [_playerItem removeObserver:self forKeyPath:@"status"];
    [_playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
    [_player removeTimeObserver:_playTimeObserver];
    _playTimeObserver = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setMaxDuratuin:(float)total{
    self.playSliderProgress.maximumValue = total;
    self.totalTime.text = [Utils stringWithTime:self.playSliderProgress.maximumValue];
}

#pragma mark - _playTimeObserver
- (void)monitoringPlayback:(AVPlayerItem *)item {
    WeakSealf(ws);
    //这里设置每秒执行30次
    _playTimeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 30) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {

            // 计算当前在第几秒
            float currentPlayTime = (double)item.currentTime.value/item.currentTime.timescale;
            [ws updateVideoSlider:currentPlayTime];
    }];
}

- (void)updateVideoSlider:(float)currentTime{
    self.playSliderProgress.value = currentTime;
    self.currentTime.text = [Utils stringWithTime:currentTime];
}

- (void)setlandscapeLayout{
    self.isLandscape = YES;
    self.frame=[UIScreen mainScreen].bounds;
    
//    [self.fullButton setImage:[self imageWithName:@"player_half"] forState:UIControlStateNormal];
}

- (void)setPortraitLayout{
    self.isLandscape = NO;
    self.frame=_oldFrame;
//    [self.fullButton setImage:[self imageWithName:@"player_full"] forState:UIControlStateNormal];
}

- (void)play{
    _isPlaying = YES;
    [_player play];
    [self.playButton  setImage:[self imageWithName:@"player_stop"] forState:UIControlStateNormal];
    [self startTimer];//开始播放的时候启动timer定时隐藏控制栏
    self.player_Pause.hidden = YES;
}


- (void)pause{
    _isPlaying = NO;
    [_player pause];
    [self.playButton  setImage:[self imageWithName:@"player_play"] forState:UIControlStateNormal];
    [timer invalidate];//暂停播放的时候显示控制栏并取消timer
    self.player_Pause.hidden = NO;
    if (self.playButton.bottom_LL>self.playerView.bottom_LL) {
        [UIView animateWithDuration:0.3 animations:^{
            self.playButton.top_LL -= 44;
            self.currentTime.top_LL -= 44;
            self.totalTime.top_LL -= 44;
            self.playSliderProgress.top_LL -= 44;
            self.bottomView.top_LL -= 44;
        }];
    }
}


-(UIViewController *)viewController {
    UIResponder *next = self.nextResponder;
    do {
        if ([next isKindOfClass:[UIViewController class]]) {
            return (UIViewController *)next;
        } else {
            next = next.nextResponder;
        }
    } while (next);
    return nil;
}

- (void)dealloc
{
    [timer invalidate];
    [self removeObserverAndNotification];
    NSLog(@"播放器释放");
}

- (UIImage *)imageWithName:(NSString *)imageName {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"NvSellerResource" ofType:@"bundle"];
    NSBundle *myBundle = [NSBundle bundleWithPath:path];
    NSString *imagePath = [myBundle pathForResource:imageName ofType:@"png"];
    return [UIImage imageWithContentsOfFile:imagePath];
}

@end
